package com.sudo.service.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.sudo.common.enums.SysStatus;
import com.sudo.common.constant.UserConstant;
import com.sudo.common.utils.PagedGridResult;
import com.sudo.dao.admin.entity.SysButton;
import com.sudo.dao.admin.entity.SysRoleButton;
import com.sudo.dao.admin.entity.SysRoleMenu;
import com.sudo.dao.admin.mapper.SysButtonMapper;
import com.sudo.dao.admin.mapper.SysMenuMapperCustom;
import com.sudo.dao.admin.mapper.SysRoleButtonMapper;
import com.sudo.dao.admin.model.bo.*;
import com.sudo.dao.admin.model.vo.SysRoleButtonVO;
import com.sudo.service.admin.service.SysButtonService;
import com.sudo.service.admin.service.AdminBaseService;
import com.sudo.service.admin.service.SysRedisAuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author 为道日损 2020-04-28 8:37
 * webSite：https://www.sudo.ren
 */
@Service
public class SysButtonServiceImpl extends AdminBaseService implements SysButtonService {
    @Resource
    private SysRedisAuthService sysRedisAuthService;
    @Resource
    private SysButtonMapper sysButtonMapper;
    @Resource
    private SysRoleButtonMapper sysRoleButtonMapper;
    @Resource
    private SysMenuMapperCustom sysMenuMapperCustom;

    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public SysButton getSysButtonByMenuButtonCode(String menuCode, String buttonCode) {
        Example example = new Example(SysButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysButton.Field.menuCode, menuCode);
        criteria.andEqualTo(SysButton.Field.buttonCode, buttonCode);
        return sysButtonMapper.selectOneByExample(example);
    }

    /**
     * 通过菜单code获取对应的button
     * @param sysButtonQueryBO menuCode
     * @return list
     */
    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public PagedGridResult getSysButtonByMenuCode(SysButtonQueryBO sysButtonQueryBO) {
        PageHelper.startPage(sysButtonQueryBO.getPage(), sysButtonQueryBO.getLimit());
        Example example = new Example(SysButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysButton.Field.menuCode, sysButtonQueryBO.getMenuCode());

        List<SysButton> sysButtons = sysButtonMapper.selectByExample(example);
        return setterPagedGrid(sysButtons, sysButtonQueryBO.getPage());
    }

    /**
     * 修改button
     * @param sysButtonUpdateBO sysButtonUpdateBO
     * @return int
     */
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int updateSysButtonByMenuButtonCode(SysButtonUpdateBO sysButtonUpdateBO) {
        //查询原始数据
        SysButton oldSysButton = getSysButtonByMenuButtonCode(
                sysButtonUpdateBO.getMenuCode(), sysButtonUpdateBO.getButtonCode());


        Example example = new Example(SysButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysButton.Field.menuCode, sysButtonUpdateBO.getMenuCode());
        criteria.andEqualTo(SysButton.Field.buttonCode,sysButtonUpdateBO.getButtonCode());

        SysButton sysButton = new SysButton();
        BeanUtils.copyProperties(sysButtonUpdateBO, sysButton,SysButton.Field.menuCode,SysButton.Field.buttonCode);
        if (!SysStatus.ON.name().equals(sysButton.getStatus())) {
            sysButton.setStatus(SysStatus.OFF.name());
        }
        boolean isEqual = oldSysButton.getStatus().equals(sysButtonUpdateBO.getStatus());
        int affectCount = sysButtonMapper.updateByExampleSelective(sysButton, example);

        //====== redis ======
        // redis_menu_button (更新按钮)
        // redis_role_permission (更新可用角色-可用菜单-可用按钮)
        if (!isEqual && affectCount > 0) {
            List<SysRoleMenu> sysRoleMenuList = sysMenuMapperCustom.getRoleMenuByMenuCodeAndRoleStatus(
                    sysButtonUpdateBO.getMenuCode(), SysStatus.ON.name());
            if (SysStatus.ON.name().equals(sysButtonUpdateBO.getStatus())) {
                //on
                for (SysRoleMenu rm : sysRoleMenuList) {
                    sysRedisAuthService.setRedisRolePermissionToRedis(rm.getRoleCode(),rm.getMenuCode(),sysButtonUpdateBO.getButtonCode());
                }
            } else {
                //off
                for (SysRoleMenu rm : sysRoleMenuList) {
                    sysRedisAuthService.delRedisRolePermissionFromRedis(rm.getRoleCode(),rm.getMenuCode(),sysButtonUpdateBO.getButtonCode());
                }
            }
        }
        return affectCount;
    }

    /**
     * 给菜单新增button
     * @param sysButtonAddBO sysButtonAddBO
     * @return int
     */
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int addSysButton(SysButtonAddBO sysButtonAddBO) {
        SysButton sysButton = new SysButton();
        BeanUtils.copyProperties(sysButtonAddBO,sysButton);

        //给超级管理员添加权限
        SysRoleButton sysRoleButton = new SysRoleButton();
        sysRoleButton.setRoleCode(UserConstant.SUPER_ADMIN);
        sysRoleButton.setMenuCode(sysButton.getMenuCode());
        sysRoleButton.setButtonCode(sysButton.getButtonCode());
        sysRoleButtonMapper.insertSelective(sysRoleButton);

        int affectCount = sysButtonMapper.insertSelective(sysButton);

        // ====== redis ======
        if (affectCount > 0 && SysStatus.ON.name().equals(sysButtonAddBO.getStatus())) {
            // redis_menu_button (新增可用菜单-可用按钮)
            sysRedisAuthService.setRedisMenuButtonToRedis(sysButton.getMenuCode() ,sysButton.getButtonCode());

            // redis_role_permission (新增超级管理员权限)
            sysRedisAuthService.setRedisRolePermissionToRedis(
                    UserConstant.SUPER_ADMIN,
                    sysButton.getMenuCode(),
                    sysButton.getButtonCode()
            );
        }
        return affectCount;
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int deleteSysButtonByMenuButtonCode(SysButtonDeleteBO sysButtonDeleteBO) {
        Example example = new Example(SysButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysButton.Field.menuCode, sysButtonDeleteBO.getMenuCode());
        criteria.andEqualTo(SysButton.Field.buttonCode, sysButtonDeleteBO.getButtonCode());

        //删除角色-菜单-按钮关联关系
        Example example1 = new Example(SysRoleButton.class);
        Example.Criteria criteria1 = example1.createCriteria();
        criteria1.andEqualTo(SysButton.Field.buttonCode, sysButtonDeleteBO.getButtonCode());
        criteria1.andEqualTo(SysButton.Field.menuCode, sysButtonDeleteBO.getMenuCode());
        sysRoleButtonMapper.deleteByExample(example1);

        int affectCount = sysButtonMapper.deleteByExample(example);

        //====== redis ======
        // redis_menu_button (删除可用菜单-可用按钮)
        // redis_role_permission (删除可用角色-可用菜单-可用按钮)
        if (affectCount > 0) {
            List<SysRoleButton> sysRoleButtonList = getRoleButtonByMenuButtonCode(sysButtonDeleteBO);
            for (SysRoleButton rb :sysRoleButtonList) {
                sysRedisAuthService.delRedisRolePermissionFromRedis(rb.getRoleCode(), rb.getMenuCode(), rb.getButtonCode());
            }
        }

        return affectCount;
    }

    /**
     * 判断buttonCode是否存在
     * @param buttonCode buttonCode
     * @return boolean
     */
    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public boolean isButtonCodeExist(String menuCode ,String buttonCode) {
        Example example = new Example(SysButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysButton.Field.buttonCode, buttonCode);
        criteria.andEqualTo(SysButton.Field.menuCode, menuCode);
        List<SysButton> sysButtonList = sysButtonMapper.selectByExample(example);
        return !CollectionUtils.isEmpty(sysButtonList);
    }

    /**
     * 根据角色code获取对应权限的按钮
     * @param roleCode 角色code
     * @return list
     */
    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public List<SysRoleButtonVO> getButtonCodeByRoleMenuCode(String roleCode , String menuCode) {
        Example buttonExample = new Example(SysButton.class);
        buttonExample.selectProperties(
                SysButton.Field.buttonName,
                SysButton.Field.buttonCode,
                SysButton.Field.menuCode,
                SysButton.Field.status);
        Example.Criteria criteria = buttonExample.createCriteria();
        criteria.andEqualTo(SysButton.Field.menuCode, menuCode);
        List<SysButton> sysButtonList = sysButtonMapper.selectByExample(buttonExample);

        List<SysRoleButton> sysRoleButtonList;
        if (StringUtils.isNotBlank(roleCode)) {
            Example roleButtonexample = new Example(SysRoleButton.class);
            roleButtonexample.selectProperties(
                    SysRoleButton.Filed.roleCode,
                    SysRoleButton.Filed.buttonCode,
                    SysRoleButton.Filed.menuCode);
            Example.Criteria roleButtoneCriteria = roleButtonexample.createCriteria();
            roleButtoneCriteria.andEqualTo(SysRoleButton.Filed.roleCode,roleCode);
            roleButtoneCriteria.andEqualTo(SysRoleButton.Filed.menuCode,menuCode);
            sysRoleButtonList = sysRoleButtonMapper.selectByExample(roleButtonexample);
        }else {
            sysRoleButtonList = new ArrayList<>();
        }


        List<SysRoleButtonVO> sysRoleButtonVOList = new ArrayList<>();
        for (SysButton sysButton : sysButtonList) {
            SysRoleButtonVO sysRoleButtonVO = new SysRoleButtonVO();
            BeanUtils.copyProperties(sysButton, sysRoleButtonVO);
            for (SysRoleButton sysRoleButton : sysRoleButtonList) {
                if (sysRoleButton.getMenuCode().equals(sysButton.getMenuCode())
                        && sysRoleButton.getButtonCode().equals(sysButton.getButtonCode())) {
                    sysRoleButtonVO.setRoleCode(sysRoleButton.getRoleCode());
                }
            }
            sysRoleButtonVOList.add(sysRoleButtonVO);
        }
        return sysRoleButtonVOList;
    }

    /**
     * 根据menuButtonCode 获取SysRoleButton
     * @param sysButtonDeleteBO 菜单按钮
     * @return list
     */
    @Override
    public List<SysRoleButton> getRoleButtonByMenuButtonCode(SysButtonDeleteBO sysButtonDeleteBO) {
        Example example = new Example(SysRoleButton.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysRoleButton.Filed.menuCode, sysButtonDeleteBO.getMenuCode());
        criteria.andEqualTo(SysRoleButton.Filed.buttonCode, sysButtonDeleteBO.getButtonCode());
        return sysRoleButtonMapper.selectByExample(example);
    }


}
